package com.ninong.ker.admin.sevice.impl;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.sql.DataSource;

import com.ninong.ker.admin.rest.vo.TenantVO;
import com.ninong.ker.admin.service.dto.TenantDTO;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import com.ninong.ker.admin.domain.Dept;
import com.ninong.ker.admin.domain.Dic;
import com.ninong.ker.admin.domain.DicDetail;
import com.ninong.ker.admin.domain.Menu;
import com.ninong.ker.admin.domain.Role;
import com.ninong.ker.admin.domain.RoleMenu;
import com.ninong.ker.admin.domain.Tenant;
import com.ninong.ker.admin.domain.TenantMenu;
import com.ninong.ker.admin.domain.TenantUser;
import com.ninong.ker.admin.domain.User;
import com.ninong.ker.admin.domain.UserRole;
import com.ninong.ker.admin.mapper.DeptMapper;
import com.ninong.ker.admin.mapper.DicDetailMapper;
import com.ninong.ker.admin.mapper.DicMapper;
import com.ninong.ker.admin.mapper.MenuMapper;
import com.ninong.ker.admin.mapper.RoleMapper;
import com.ninong.ker.admin.mapper.RoleMenuMapper;
import com.ninong.ker.admin.mapper.TenantMapper;
import com.ninong.ker.admin.mapper.TenantMenuMapper;
import com.ninong.ker.admin.mapper.TenantUserMapper;
import com.ninong.ker.admin.mapper.UserMapper;
import com.ninong.ker.admin.mapper.UserRoleMapper;
import com.ninong.ker.admin.sevice.TenantService;
import com.ninong.ker.admin.sevice.UserService;
import com.ninong.ker.common.exception.CmdException;
import com.ninong.ker.common.tools.Constants;
import com.ninong.ker.common.tools.SystemConstant;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.crypto.SecureUtil;

/**
 * saas租户 服务实现类
 *
 * @author jmz
 * @since 2020-09-12
 */
@Service
@Transactional(rollbackFor = RuntimeException.class)
public class TenantServiceImpl extends ServiceImpl<TenantMapper, Tenant> implements TenantService {

	private static final String MENU = "menu";
	private static final String TENANT_TYPE = "1";

	@Autowired
	private TenantMenuMapper tenantMenuMapper;
	@Autowired
	private MenuMapper menuMapper;
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private TenantUserMapper tenantUserMapper;
	@Autowired
	private RoleMapper roleMapper;
	@Autowired
	private RoleMenuMapper roleMenuMapper;
	@Autowired
	private UserRoleMapper userRoleMapper;

	@Autowired
	private DicDetailMapper dicDetailMapper;

	@Autowired
	private DicMapper dicMapper;

	@Autowired
	private DeptMapper deptMapper;

//	@Qualifier("multipleDataSource")
//	@Autowired
//	private DataSource dataSource;

	@Autowired
	private UserService userService;

//	private final DynamicDatabaseProperties dynamicDatabaseProperties;
//
//	public TenantServiceImpl(DynamicDatabaseProperties dynamicDatabaseProperties) {
//		this.dynamicDatabaseProperties = dynamicDatabaseProperties;
//	}

	@Override
	public PageInfo<TenantVO> listPage(TenantDTO dto) {
		PageHelper.startPage(dto.getCurrentPage(), dto.getPageSize());
		LambdaQueryWrapper<Tenant> query = new LambdaQueryWrapper<>();
		query.eq(Tenant::getDeleted, Constants.DEFAULT_YES);
		List<TenantVO> tenants = baseMapper.selectListPage(dto);
		return new PageInfo<>(tenants);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void create(TenantDTO dto) throws SQLException {
		Tenant tenant = null;
		if (StringUtils.isEmpty(dto.getId())) {
			if (checkTenantNameExist(dto)) {
				throw new CmdException("租户名称已存在");
			}
			if (checkMobileExists(dto)) {
				throw new CmdException("手机号已经被其他租户绑定");
			}
			tenant = new Tenant();
			BeanUtils.copyProperties(dto, tenant);
			tenant.setDeleted(Constants.DEFAULT_YES);
			tenant.setEnabled(Constants.DEFAULT_YES);
			tenant.setUpdateTime(new Date());
		} else {
			tenant = baseMapper.selectById(dto.getId());
			BeanUtils.copyProperties(dto, tenant);
		}

		saveOrUpdate(tenant);
		saveUser(dto, tenant);
	}

	/**
	 * 校验租户名称是否存在
	 *
	 * @param dto
	 */
	private boolean checkTenantNameExist(TenantDTO dto) {
		QueryWrapper<Tenant> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(Tenant::getTenantName, dto.getTenantName());
		if (dto.getId() == null) {
			queryWrapper.isNotNull("id");
		} else {
			queryWrapper.lambda().ne(Tenant::getId, dto.getId());
		}
		List<Tenant> tenantList = baseMapper.selectList(queryWrapper);
		if (tenantList != null && tenantList.size() > 0) {
			return true;
		}
		return false;

	}

	/**
	 * 校验手机号是否重复
	 *
	 * @param dto
	 */
	private boolean checkMobileExists(TenantDTO dto) {
		if (StringUtils.isEmpty(dto.getPhone())) {
			throw new CmdException("手机号不能为空");
		}
		QueryWrapper<User> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(User::getPhone, dto.getPhone());
		queryWrapper.lambda().eq(User::getDeleted, Constants.DEFAULT_YES);
		if (dto.getId() == null) {
			queryWrapper.isNotNull("id");
		} else {
			queryWrapper.lambda().ne(User::getId, dto.getId());
		}
		List<User> userList = userMapper.selectList(queryWrapper);
		if (userList != null && userList.size() > 0) {
			return true;
		}
		return false;
	}

	private User saveUser(TenantDTO dto, Tenant tenant) {
		List<User> userList = userService.selectTenantAdminUser(tenant.getId());
		if (userList != null && userList.size() > 0) {
			User user = userList.get(0);
			user.setPhone(tenant.getPhone());
			userMapper.updateById(user);
			return user;
		} else {
			Dept dept = new Dept();
			dept.setTenantId(tenant.getId());
			dept.setPid("0");
			dept.setName("默认部门");
			deptMapper.insert(dept);
			User user = new User();
			user.setPhone(dto.getPhone());
			String salt = UUID.fastUUID().toString();
			user.setSalt(salt);
			String password = SecureUtil.md5(salt + Constants.DEFAULT_PASSWORD);
			user.setPassword(password);
			user.setDeleted(Constants.DEFAULT_YES);
			user.setEnabled(Constants.DEFAULT_YES);
			user.setType(TENANT_TYPE);
			user.setMultipleDb(dto.getMultipleDb());
			user.setDeptId(dept.getId());
			user.setTenantId(tenant.getId());
			user.setNickName("管理员");
			userMapper.insert(user);
			// 新增的租户用户绑定租户关系
			TenantUser tenantUser = new TenantUser();
			tenantUser.setTenantId(tenant.getId());
			tenantUser.setUserId(user.getId());
			tenantUserMapper.insert(tenantUser);
			LambdaQueryWrapper<Dic> dicQuery = new LambdaQueryWrapper<>();
			dicQuery.eq(Dic::getTenantId, SystemConstant.ROOT_PARENT_ID);
			List<Dic> dics = dicMapper.selectList(dicQuery);
			dics.forEach(dic -> {
				LambdaQueryWrapper<DicDetail> dicDetailQuery = new LambdaQueryWrapper<>();
				dicDetailQuery.eq(DicDetail::getDicId, dic.getId());
				List<DicDetail> details = dicDetailMapper.selectList(dicDetailQuery);
				dic.setId(null);
				dic.setTenantId(tenant.getId());
				dicMapper.insert(dic);
				details.forEach(detail -> {
					detail.setId(null);
					detail.setDicId(dic.getId());
					detail.setTenantId(tenant.getId());
					dicDetailMapper.insert(detail);
				});
			});
			return user;
		}

	}

	@Override
	public void delete(String[] id) {
		Tenant tenant = baseMapper.selectById(id);
		if (BeanUtil.isEmpty(tenant)) {
			throw new CmdException("租户不存在");
		}
		tenant.setDeleted(true);
		updateById(tenant);
	}

	@Override
	public TenantVO get(String id) {
		QueryWrapper<Tenant> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(Tenant::getId, id);
		queryWrapper.lambda().eq(Tenant::getDeleted, Constants.DEFAULT_YES);
		Tenant tenant = getOne(queryWrapper);
		TenantVO vo = new TenantVO();
		if (ObjectUtils.isNotEmpty(tenant)) {
			BeanUtils.copyProperties(tenant, vo);
//			LambdaQueryWrapper<TenantData> wrapper = new LambdaQueryWrapper<>();
//			wrapper.eq(TenantData::getTenantId, id);
//			wrapper.eq(TenantData::getDeleted, Constants.DEFAULT_YES);
//			if (tenant.getMultipleDb()) {
//				TenantData tenantData = tenantDataInfoMapper.selectOne(wrapper);
//				vo.setUrl(tenantData.getUrl());
//				vo.setPassword(tenantData.getPassword());
//				vo.setUsername(tenantData.getUsername());
//			}
		}
		return vo;
	}

	@Override
	public void updateTenantMenuByTenantId(String tenantId, List<String> menuIds) throws SQLException {
		LambdaQueryWrapper<TenantMenu> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(TenantMenu::getTenantId, tenantId);
		tenantMenuMapper.delete(queryWrapper);
		menuIds.forEach(id -> {
			TenantMenu entity = new TenantMenu(id, tenantId);
			tenantMenuMapper.insert(entity);
		});
		Tenant tenant = baseMapper.selectById(tenantId);
//		if (tenant.getMultipleDb()) {
//			/**
//			 * 跨库操作租户数据库 新增默认权限
//			 */
//			LambdaQueryWrapper<TenantData> wrapper = new LambdaQueryWrapper<>();
//			wrapper.eq(TenantData::getTenantId, tenantId);
//			wrapper.eq(TenantData::getDeleted, Constants.DEFAULT_YES);
//			TenantData tenantData = tenantDataInfoMapper.selectOne(wrapper);
//			DruidDataSource ds = new DruidDataSource();
//			ds.setUrl(tenantData.getUrl());
//			ds.setUsername(tenantData.getUsername());
//			ds.setPassword(tenantData.getPassword());
//			Db db = Db.use(ds);
//			for (String id : menuIds) {
//				Menu menu = menuMapper.selectById(id);
//				db.insert(Entity.create("fw_menu").set("id", id).set("pid", menu.getPid()).set("type", menu.getType())
//						.set("name", menu.getName()).set("sort", menu.getSort()).set("icon", menu.getIcon())
//						.set("permission", menu.getPermission()).set("create_time", menu.getCreateTime())
//						.set("update_time", menu.getUpdateTime()).set("path", menu.getPath())
//						.set("component", menu.getComponent()).set("form_code", menu.getFormCode())
//						.set("data_id", menu.getDataId()).set("task_key", menu.getTaskKey()));
//				db.insert(Entity.create("fw_roles_menus").set("menu_id", id).set("role_id",
//						"0ca8c48ae5c63bf66703e56535a241e5"));
//			}
//		} else {
			// 非多数据源时候 默认新增一个角色 赋值全部权限
			// 如果有了就不操作
			LambdaQueryWrapper<Role> query = new LambdaQueryWrapper<>();
			query.eq(Role::getTenantId, tenantId);
			Long count = roleMapper.selectCount(query);
			if (count.longValue() == Constants.ZERO.longValue()) {
				Role role = new Role();
				role.setName("管理员");
				role.setDescription("可修改");
				role.setNonEditable(Constants.NO);
				role.setTenantId(tenantId);
				roleMapper.insert(role);
				// 给默认角色绑定权限菜单
				menuIds.forEach(id -> {
					RoleMenu entity = new RoleMenu(id, role.getId());
					roleMenuMapper.insert(entity);
				});
				// 把默认角色和超级管理员绑定
				String phone = tenant.getPhone();
				Map<String, Object> param = Maps.newHashMap();
				param.put("tenantId", tenantId);
				param.put("phone", phone);
				User user = baseMapper.selectUserTenant(param);
				if (ObjectUtils.isEmpty(user)) {
					throw new CmdException("用户不存在");
				} else {
					UserRole entity = new UserRole();
					entity.setUserId(user.getId());
					entity.setRoleId(role.getId());
					userRoleMapper.insert(entity);
				}
			}
//		}
	}

	@Override
	public List<String> listTreeByTenantId(String tenantId) {
		LambdaQueryWrapper<Menu> query = new LambdaQueryWrapper<>();
		query.ne(Menu::getType, MENU);
		List<Menu> menus = menuMapper.selectList(query);
		List<String> menuIds = menus.stream().map(Menu::getId).collect(Collectors.toList());
		LambdaQueryWrapper<TenantMenu> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(TenantMenu::getTenantId, tenantId);
		List<TenantMenu> list = tenantMenuMapper.selectList(queryWrapper);
		List<String> checkedIds = list.stream().map(TenantMenu::getMenuId).collect(Collectors.toList());
		List<String> data = menuIds.stream().filter(item -> checkedIds.contains(item)).collect(Collectors.toList());
		return data;
	}

	private Tenant getTenantByName(String tenantName) {
		QueryWrapper<Tenant> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(Tenant::getTenantName, tenantName);
		queryWrapper.lambda().eq(Tenant::getDeleted, Constants.DEFAULT_YES);
		return getOne(queryWrapper);
	}

	@Override
	public void enableTenant(String id, Boolean enable) {
		Tenant entity = new Tenant();
		entity.setId(id);
		entity.setEnabled(enable);
		baseMapper.updateById(entity);

	}

	@Override
	public void resetPassword(String tenantId) {
		List<User> userList = userService.selectTenantAdminUser(tenantId);
		if (userList == null || userList.size() == 0) {
			throw new CmdException("用户不存在");
		} else {
			User user = userList.get(0);
			String salt = UUID.fastUUID().toString();
			user.setSalt(salt);
			String password = SecureUtil.md5(salt + Constants.DEFAULT_PASSWORD);
			user.setPassword(password);
			userMapper.updateById(user);
		}

	}
}
